#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2
import numpy as np
import pytesseract
import sys
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import imagehash

import json
from pydash import py_
from PIL import Image
import struct
from sklearn.neighbors import BallTree

from log import get_logger

logger = get_logger(__name__)

select_card_location = {
    '1': [138, 155, 368, 553],
    '2': [396, 155, 625, 553],
    '3': [653, 155, 883, 553],
    '4': [910, 155, 1141, 553]
}


def card_location(idx):
    arr = select_card_location[str(idx)]
    return [round((arr[0] + arr[2]) / 2), round((arr[1] + arr[3]) / 2)]


def cut_card(img, idx):
    arr = select_card_location[str(idx)]
    return img[arr[1]:arr[3], arr[0]:arr[2]]


def hamming_dist_to_array(s):
    ll = [list(bin(int(s[i], 16))[2:].zfill(4)) for i in range(0, len(s))]
    return [item for sublist in ll for item in sublist]


def array_to_hamming_dist(arr):
    return "".join([format(int("".join(arr[i:i + 4]), 2), 'x') for i in range(0, len(arr), 4)])


def card_data_to_ball_tree():
    f = open("/home/liusen/IdeaWorkspace/wechat-jump/mijing_card.json", encoding='utf-8')
    arr = json.load(f)
    items = arr["items"]
    item_dict = {items[i]["upper_half_phash"]: items[i] for i in range(0, len(items))}
    # logger.debug(item_dict)
    index_data = list(map(lambda x: hamming_dist_to_array(x["upper_half_phash"]), items))
    # logger.debug(index_data)
    return BallTree(index_data, leaf_size=50, metric='hamming'), index_data, item_dict


ballt, index_data, item_dict = card_data_to_ball_tree()


def hamming_dist(s1, s2):
    assert len(s1) == len(s2)
    return 1 - sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)]) * 1. / (32 * 32 / 4)


def hamming_dist2(s1, s2, hash_size):
    assert len(s1) == len(s2)
    # t1 = sum([abs(int(ch1, 16) - int(ch2, 16)) for ch1, ch2 in zip(s1, s2)])
    # logger.debug(t1)
    return 1 - sum([abs(int(ch1, 16) - int(ch2, 16)) for ch1, ch2 in zip(s1, s2)]) * 1. / (15 * 2 * hash_size)


disardCardList = ["灰烬之门", "军团王牌", "绊咒喷火仪"]


def discard_card(card_info):
    if card_info["cost"] >= 3:
        return True
    if card_info["name"] in disardCardList:
        return True
    return False


def handle_select_card(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    click_card = []
    for n in range(1, 5):
        # logger.debug("n={}".format(n))
        img_crop = cut_card(img, n)
        img_hash = calc_image_phash(img_crop)
        distances, neighbors = ballt.query([hamming_dist_to_array(img_hash)], k=1)
        if distances[0][0] < 0.2:
            idx = neighbors[0][0]
            card_hash = array_to_hamming_dist(index_data[idx])
            card_info = item_dict[card_hash]
            # logger.debug(card_info)
            if discard_card(card_info):
                logger.debug("n={} discard card : {}".format(n, card_info["name"]))
                click_card.append(n)
        else:
            logger.debug("n={} distances={} neighbors={}".format(n, distances, neighbors))
            return False, []
    return True, list(map(card_location, click_card))


def convert_unicode_file():
    c = open('mijing_raw.json').read()
    c = c.encode('utf-8').decode('unicode_escape')
    fo = open("mijing_card_zh.json", "w")
    fo.write(c)
    fo.close()


def calc_image_phash(img):
    h, w = img.shape[:2]
    h = round(h * 0.53)
    img = img[0:h, 0:w]
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    upper_half_phash = str(imagehash.phash(Image.fromarray(img), hash_size=16))
    return upper_half_phash


def handle_pic(o):
    img = cv2.imread("./mijing_card/" + o["pic"] + ".png")
    upper_half_phash = calc_image_phash(img)
    del o['total_phash']
    o["upper_half_phash"] = upper_half_phash
    logger.debug("pic:{} upper_half_phash:{}".format(o["pic"], upper_half_phash))
    return o


def card_data_init():
    f = open("mijing_card.json", encoding='utf-8')
    arr = json.load(f)

    logger.debug("start")
    res = py_(arr["items"]).map(handle_pic).value()
    new_mijing_card = {"items": res}
    # logger.debug(res)
    new_mijing_card = str(json.dumps(new_mijing_card, ensure_ascii=False, indent=2))
    f2 = open("mijing_card.json", 'w', encoding='utf-8')
    f2.write(new_mijing_card)
    f2.close()


if __name__ == '__main__':
    # path = '/home/liusen/IdeaWorkspace/wechat-jump/mijing/201809-special-选牌.png'
    path = '/home/liusen/IdeaWorkspace/wechat-jump/mijing2/img.png'

    img = cv2.imread(path)
    location = handle_select_card(img)
    logger.debug(location)
    # cardDataInit()
    # sys.exit()

    # img = cv2.imread("/home/liusen/IdeaWorkspace/wechat-jump/mijing_card/5a9f53a0aa49f1cc6440c277P3l70Kbp.png")
    # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # plt.imshow(img), plt.show()

    # img = cv2.imread("/home/liusen/IdeaWorkspace/wechat-jump/mijing/201809-scene-伊芙琳教堂.png")
    # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # plt.imshow(img), plt.show()

    # # 透视变换
    # img = cv2.imread('/home/liusen/IdeaWorkspace/wechat-jump/mijing/201809-scene-伊芙琳教堂.png')
    # rows, cols, ch = img.shape
    # # pts1 = np.float32([[283, 600], [1113, 600], [300, 718], [996, 718]])
    # # pts2 = np.float32([[0, 0], [900, 0], [0, 400], [900, 400]])
    # pts1 = np.float32([[354, 650], [453, 626], [359, 719], [460, 703]])
    # pts2 = np.float32([[0, 0], [400, 0], [0, 400], [400, 400]])
    # M = cv2.getPerspectiveTransform(pts1, pts2)
    # dst = cv2.warpPerspective(img, M, (400, 400))
    # plt.subplot(121), plt.imshow(img), plt.title('Input')
    # plt.subplot(122), plt.imshow(dst), plt.title('Output')
    # plt.show()

    # # 仿射变换
    # img = cv2.imread('/home/liusen/IdeaWorkspace/wechat-jump/mijing/201809-scene-伊芙琳教堂.png')
    # rows, cols, ch = img.shape
    # pts1 = np.float32([[353, 651], [453, 627], [360, 718]])
    # # pts2 = np.float32([[0, 0], [200, 0], [200, 0]])
    # pts2 = np.float32([[345, 621], [453, 627], [345, 718]])
    #
    # M = cv2.getAffineTransform(pts1, pts2)
    # dst = cv2.warpAffine(img, M, (cols, rows))
    # plt.subplot(121), plt.imshow(img), plt.title('Input')
    # plt.subplot(122), plt.imshow(dst), plt.title('Output')
    # plt.show()

    sys.exit(0)
